package org.damazio.bhtranscams;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;

/**
 * Class which actually fetches an image from the network. This fetches the
 * image in a separate thread, but calls the passed callback in the original
 * thread.
 * 
 * @author rdamazio
 */
public class CameraFetcher extends Thread {
  private final String imageUrl;
  private final FetchDoneCallback doneCallback;
  private Handler handler;
  private boolean cancelled;

  /**
   * Callback for when the image is done fetching.
   */
  public interface FetchDoneCallback {
    void onFetchDone(Bitmap cameraImage, String fetchedUrl);
  }

  /**
   * Constructor.
   * 
   * @param imageUrl the URL of the image to fetch
   * @param doneCallback the callback to call when done
   */
  public CameraFetcher(String imageUrl, FetchDoneCallback doneCallback) {
    this.imageUrl = imageUrl;
    this.doneCallback = doneCallback;

    // Created on construction so we capture the calling thread's looper
    this.handler = new Handler();
  }

  @Override
  public void run() {
    // If cancelled before it starts, just abort
    if (cancelled) {
      return;
    }

    // Build the URL to fetch
    URL uniqueUrl = uniqueUrl(imageUrl);

    // Fetch it
    final Bitmap bitmap = fetchImageDrawable(uniqueUrl);

    // Make the callback be executed in the original calling thread
    handler.post(new Runnable() {
      public void run() {
        // Cancellation point - if cancelled during fetching, don't go any further
        if (cancelled) {
          return;
        }

        doneCallback.onFetchDone(bitmap, imageUrl);
      }
    });
  }

  /**
   * Cancels the fetching that may be currently in course.
   */
  public void cancel() {
    cancelled = true;
  }

  /**
   * Actually fetches the image and decodes it into a {@link Bitmap}.
   * 
   * @param url the URL of the image to fetch
   * @return its decoded bitmap
   */
  private Bitmap fetchImageDrawable(URL url) {
    try {
      // Fetch it
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setDoInput(true);
      conn.connect();

      // Decode and return it
      return BitmapFactory.decodeStream(conn.getInputStream());
    } catch (IOException e) {
      // TODO(rdamazio): Proper error handling
      e.printStackTrace();
      return null;
    }
  }

  /**
   * Creates a unique URL by appending a timestamp-based as a parameter.
   * 
   * @param url the original URL
   * @return the URL with the proper unique parameter appended
   */
  private URL uniqueUrl(String url) {
    long nowSeconds = System.currentTimeMillis() / 1000L;
    try {
      return new URL(url + "?" + nowSeconds);
    } catch (MalformedURLException mue) {
      return null;
    }
  }
}
